package main

import (
	"context"
	"log"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"
)

func main() {
	// 修复 Go 1.22 TLS 握手失败问题：重新启用基于 RSA 密钥交换的密码套件
	// 参考: https://pkg.go.dev/crypto/tls#Config.CipherSuites
	// 如果用户没有在外部设置 GODEBUG，则设置 tlsrsakex=1
	if os.Getenv("GODEBUG") == "" {
		os.Setenv("GODEBUG", "tlsrsakex=1")
	} else {
		// 如果已有 GODEBUG 设置，检查是否已包含 tlsrsakex
		currentDebug := os.Getenv("GODEBUG")
		if !strings.Contains(currentDebug, "tlsrsakex") {
			os.Setenv("GODEBUG", currentDebug+",tlsrsakex=1")
		}
	}
	cfgPath := getenv("ULTRAPROXY_CONFIG", "conf.json")

	state, err := LoadStateFromFile(cfgPath)
	if err != nil {
		log.Fatalf("load config failed: %v", err)
	}

	// Build TLS config from state (cert per domain via SNI)
	tlsCfg, err := BuildTLSConfig(state)
	if err != nil {
		log.Fatalf("build tls config failed: %v", err)
	}

	// Reverse proxy handler (shared for 80/443)
	rp := NewProxy(state)

	// HTTP server on :80
	httpSrv := &http.Server{
		Addr:              ":80",
		Handler:           rp,
		ReadHeaderTimeout: 10 * time.Second,
		IdleTimeout:       120 * time.Second,
		MaxHeaderBytes:    1 << 20,
	}

	// HTTPS server on :443 (if there is any certificate loaded)
	httpsSrv := &http.Server{
		Addr:              ":443",
		Handler:           rp,
		TLSConfig:         tlsCfg,
		ReadHeaderTimeout: 10 * time.Second,
		IdleTimeout:       120 * time.Second,
		MaxHeaderBytes:    1 << 20,
	}

	// API server on :8080
	api := NewAPI(state, cfgPath, rp)
	apiSrv := &http.Server{
		Addr:              ":8080",
		Handler:           api.Router(),
		ReadHeaderTimeout: 10 * time.Second,
		IdleTimeout:       120 * time.Second,
		MaxHeaderBytes:    1 << 20,
	}

	go func() {
		log.Printf("API listening on %s", apiSrv.Addr)
		if err := apiSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("api server error: %v", err)
		}
	}()

	go func() {
		log.Printf("HTTP listening on %s", httpSrv.Addr)
		if err := httpSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("http server error: %v", err)
		}
	}()

	go func() {
		// Only start TLS if we have TLS enabled (tlsCfg != nil)
		if tlsCfg == nil {
			log.Printf("No TLS configured, HTTPS server not started")
			return
		}
		log.Printf("HTTPS listening on %s", httpsSrv.Addr)
		if err := httpsSrv.ListenAndServeTLS("", ""); err != nil && err != http.ErrServerClosed {
			log.Fatalf("https server error: %v", err)
		}
	}()

	// graceful shutdown
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
	<-sigCh
	log.Printf("shutting down...")

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	_ = httpSrv.Shutdown(ctx)
	_ = apiSrv.Shutdown(ctx)
	_ = httpsSrv.Shutdown(ctx)
}

func getenv(k, d string) string {
	if v := os.Getenv(k); v != "" {
		return v
	}
	return d
}
